package com.aaa.sso.service;


import com.aaa.common.bo.Member;
import com.aaa.common.util.LoginUserInfo;
import com.aaa.common.util.Result;
import com.aaa.common.util.ResultStatus;
import com.aaa.sso.util.CustomUsernamePasswordToken;
import com.aaa.sso.util.LoginType;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service("memberAuthService")
public class MemberAuthServiceImpl implements AuthService {
    @Resource
    private RedisTemplate redisTemplate;
    @Override
    public Result authUserMember(String userName, String password) {

            //收集用户信息
            AuthenticationToken usernamePasswordToken =
                    new CustomUsernamePasswordToken(userName, password, LoginType.USER.toString());
            //获取主题 Subject 当前登录用户（shiro）
            Subject subject = SecurityUtils.getSubject();
            //实例化返回的map
            Map resultMap=new HashMap();
            //登录
            try {
                subject.login(usernamePasswordToken);
                //获取用户信息
                Member member =(Member) subject.getPrincipal();
                LoginUserInfo loginUserInfo=new LoginUserInfo();
                loginUserInfo.setLoginName(member.getName());
                loginUserInfo.setHeadPic(member.getHeadPic());
                //认证成功，生成token,   currentTimeMillis 1970年到现在的毫秒数
                String token = userName+System.currentTimeMillis();
                redisTemplate.delete(redisTemplate.keys(userName+"*"));
                //修改RedisTemplate的序列化策略
                RedisSerializer<String> stringSerializer = new StringRedisSerializer();
                redisTemplate.setKeySerializer(stringSerializer);
                //由于采用了String的序列化策略，所以只接受value值类型为String的参数。
                // 放入redis集群
                redisTemplate.opsForValue().set(token,member,60, TimeUnit.MINUTES);
                //返回信息
                resultMap.put("accessToken",token);
                resultMap.put("loginUserInfo",loginUserInfo);
                //记录登录日志

                return new Result(ResultStatus.SUCCESS.getCode(),
                        ResultStatus.SUCCESS.getMessage(),resultMap);
            }/*catch (LockedAccountException e){
               resultMap.put("loginFail","用户已锁定");
            }*/
            /*catch (AccountException e){

            }catch (IncorrectCredentialsException e){

            }*/
            catch (AuthenticationException e){
                e.printStackTrace();
                resultMap.put("loginFail","用户名或者密码错误");
            }

            return new Result(ResultStatus.FAIL.getCode(),
                    ResultStatus.FAIL.getMessage(),resultMap);
    }


    @Override
    public boolean checkToken(String accessToken) {
        return redisTemplate.hasKey(accessToken);
    }
}
